package com.wardrobe.soa.api.booking_order;

import com.thoughtworks.xstream.XStream;
import com.wardrobe.dao.address.AddressDao;
import com.wardrobe.dao.booking.BookingDao;
import com.wardrobe.dao.booking_order.BookingOrderDao;
import com.wardrobe.dao.order_prepay_dao.OrderPrePayDao;
import com.wardrobe.dao.shop.ShopDao;
import com.wardrobe.domain.address.AddressBean;
import com.wardrobe.domain.booking.BookingShowBean;
import com.wardrobe.domain.booking_order.BookingOrderShowBean;
import com.wardrobe.domain.booking_order.BookingOrderbean;
import com.wardrobe.domain.common.BookingOrderPayFromBean;
import com.wardrobe.domain.common.WeixinPayResult;
import com.wardrobe.domain.orderprepay.OrderPrepayBean;
import com.wardrobe.domain.orderprepay.OrderPrepayShowBean;
import com.wardrobe.domain.shop.ShopShowBean;
import com.wardrobe.soa.common.WeChatConsant;
import com.wardrobe.soa.utils.CommonUtil;
import com.wardrobe.soa.utils.HttpClientUtils;
import com.wardrobe.soa.utils.NumberUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

/**
 * Created by Administrator on 2018/11/20.
 */
@Service
public class BookingOrderService {
    private static final Logger logger = LoggerFactory.getLogger(BookingOrderService.class);
    @Autowired
    private BookingOrderDao bookingOrderDao;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private BookingDao bookingDao;
    @Autowired
    private AddressDao addressDao;
    @Autowired
    private OrderPrePayDao orderPrePayDao;

    @Transactional
    public synchronized long saveBookingOrder(BookingOrderbean orderbean){
        orderbean.setOrderId(System.currentTimeMillis()+new Random().nextInt(10));
        int flag = bookingOrderDao.insertBookingOrder(orderbean);
        if (flag==1){
            return orderbean.getOrderId();
        }else {
            return 0;
        }
    }
    public int modifyOrderStatus(long orderId, int status){
        return bookingOrderDao.updateBookingOrderByOrderId(orderId,status);
    }
    public List<BookingOrderResponse> bookingOrderList(long userId, int status){
        List<BookingOrderShowBean> bookingList = bookingOrderDao.selectBookingOrder(userId, status);
        List<BookingOrderResponse> list = new ArrayList<>();
        bookingList.stream().forEach(bookingOrder->{
            ShopShowBean shop = shopDao.selectShopById(bookingOrder.getShopId());
            BookingShowBean bookingShowBean = bookingDao.selectBookingById(bookingOrder.getBookingId());
            bookingOrder.setBookingTime(bookingOrder.getBookingTime().substring(0,bookingOrder.getBookingTime().length()-2));
            bookingOrder.setCreateTime(bookingOrder.getCreateTime().substring(0,bookingOrder.getCreateTime().length()-2));
            BookingOrderResponse response =  BookingOrderResponse.builder()
                    .id(bookingOrder.getId())
                    .shopId(bookingOrder.getShopId())
                    .orderId(bookingOrder.getOrderId())
                    .shopName(shop.getShopName())
                    .showPicture(bookingShowBean.getShowPicture().split(";").length>0?bookingShowBean.getShowPicture().split(";")[0]:"")
                    .name(bookingShowBean.getName())
                    .bookingTime(bookingOrder.getBookingTime())
                    .createTime(bookingOrder.getCreateTime())
                    .price(bookingOrder.getPayPrice())
                    .telphone(shop.getTelphone())
                    .status(bookingOrder.getStatus())
                    .build();
            list.add(response);
        });
        return list;
    }
    public BookingOrderDetail getBookingOrderDetails(long orderId){
        BookingOrderShowBean bookingOrder = bookingOrderDao.selectBookingOrderByOrderId(orderId);
        ShopShowBean shop = shopDao.selectShopById(bookingOrder.getShopId());
//        AddressBean addressBean = addressDao.selectDefaultAddress(bookingOrder.getUserId());
        AddressBean addressBean =addressDao.selectAddressById(bookingOrder.getAddressId());
        BookingShowBean bookingShowBean = bookingDao.selectBookingById(bookingOrder.getBookingId());
        bookingOrder.setBookingTime(bookingOrder.getBookingTime().substring(0,bookingOrder.getBookingTime().length()-2));
        bookingOrder.setCreateTime(bookingOrder.getCreateTime().substring(0,bookingOrder.getCreateTime().length()-2));
        return BookingOrderDetail.builder()
                .id(bookingOrder.getId())
                .orderId(orderId)
                .addressBean(addressBean)
                .shopId(bookingOrder.getShopId())
                .shopName(shop.getShopName())
                .bookingId(bookingOrder.getBookingId())
                .name(bookingShowBean.getName())
                .showPicture(bookingShowBean.getShowPicture().split(";").length>0?bookingShowBean.getShowPicture().split(";")[0]:"")
                .remark(bookingOrder.getRemark())
                .price(bookingOrder.getPayPrice())
                .bookingTime(bookingOrder.getBookingTime())
                .telphone(shop.getTelphone())
                .createTime(bookingOrder.getCreateTime())
                .payTime(bookingOrder.getPayTime())
                .build();
    }
    @Transactional
    public Map<String,Object> weixinPay(BookingOrderPayFromBean fromBean) throws Exception {
        long orderId = NumberUtil.parseLong(fromBean.getOutTradeNo(), 0);
        OrderPrepayShowBean showBean = orderPrePayDao.getOrderPrepayByOrderId(orderId);
        if(showBean!=null){
            long createTime = showBean.getCreateTime();
            long nowTime = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
            double hours= CommonUtil.getBetweenHours(createTime,nowTime);
            if(hours>2){
                orderPrePayDao.deleteOrderPrepay(orderId);
                bookingOrderDao.updateBookingOrderByOrderId(orderId,-1);
            }else{
                //直接给prepayid
                TreeMap<String,Object> payMap = new TreeMap();
                payMap.put("appid", WeChatConsant.appId);
                payMap.put("partnerid",WeChatConsant.wechatPayMchId);
                payMap.put("prepayid",showBean.getPrepayId());
                payMap.put("package","Sign=WXPay");
                payMap.put("noncestr",String.valueOf(System.currentTimeMillis()));
                payMap.put("timestamp",LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));
                logger.warn("payMap={}",payMap);
                payMap.put("sign",CommonUtil.getSignValue(payMap));
                return payMap;
            }
        }else{
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("appid", WeChatConsant.appId);
            params.put("mch_id",WeChatConsant.wechatPayMchId);
            params.put("nonce_str",String.valueOf(System.currentTimeMillis()));
            params.put("body",fromBean.getBody());
            params.put("out_trade_no",fromBean.getOutTradeNo());
            params.put("total_fee",fromBean.getTotalFee());
            params.put("spbill_create_ip",fromBean.getSpbillCreateIp());
            params.put("notify_url", CommonUtil.getRealmNameUrl()+fromBean.getNotifyUrl());
            params.put("trade_type",fromBean.getTradeType());
            String sign = CommonUtil.getSignValue(params);
            logger.warn("sign={}",sign);
            String xmlData = CommonUtil.formatUnifiedorderParam(params, sign);
            logger.warn("xmlData={}",xmlData);
            String post = HttpClientUtils.sendPost(WeChatConsant.weixin_pay_unifiedorder_url, xmlData);
            Map<String, Object> res = CommonUtil.getXmlValue(post);
            logger.warn("res={}",res);
            if(res.get("return_code").equals(WeChatConsant.SUCCESS)){
                TreeMap<String,Object> payMap = new TreeMap();
                payMap.put("appid", WeChatConsant.appId);
                payMap.put("partnerid",res.get("mch_id"));
                payMap.put("prepayid",res.get("prepay_id"));
                payMap.put("package","Sign=WXPay");
                payMap.put("noncestr",res.get("nonce_str"));
                payMap.put("timestamp",LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));
                logger.warn("payMap={}",payMap);
                payMap.put("sign",CommonUtil.getSignValue(payMap));
                OrderPrepayBean bean = new OrderPrepayBean();
                bean.setOrderId(orderId);
                bean.setCreateTime(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));
                bean.setPrepayId((String) res.get("prepay_id"));
                int flag = orderPrePayDao.insertOrderPrepay(bean);
                if(flag==1){
                    return payMap;
                }else{
                    return null;
                }
            }
            return res;
        }
        return null;
    }
    @Transactional
    public void weixinCallBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        StringBuffer sb = new StringBuffer();
        String reqParamss = CommonUtil.read(request.getInputStream());
        logger.info("-------支付结果:{}",reqParamss);
        if(reqParamss==null||"".equals(reqParamss)){
            logger.warn("weixinCallBack Request data error");
        }else{
            XStream xStream = new XStream();
            xStream.alias("xml", WeixinPayResult.class);
            WeixinPayResult returnInfo = (WeixinPayResult)xStream.fromXML(reqParamss);
            String return_code=returnInfo.getReturn_code();
            if(return_code.equals(WeChatConsant.SUCCESS)){//支付成功
                if(returnInfo.getResult_code().equals(WeChatConsant.SUCCESS)){
                    long orderId = NumberUtil.parseLong(returnInfo.getOut_trade_no(), 0);
                    if(orderId == 0){
                        logger.warn("orderId 格式错误！");
                        throw new Exception();
                    }
                    BookingOrderShowBean bookingOrder = bookingOrderDao.selectBookingOrderByOrderId(orderId);
                    if(bookingOrder.getStatus()==1){
                        sb.append("<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>");
                    }else{
                        int flag = bookingOrderDao.updateBookingOrderByOrderId(orderId,1);
                        if(flag != 1){
                            logger.warn("订单状态修改失败！");
                        }else{
                            sb.append("<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>");
                        }
                    }
                }else{
                    sb.append("<xml><return_code>FAIL</return_code><return_msg>"+returnInfo.getReturn_msg()+"</return_msg></xml>");
                }
            }else{
                sb.append("<xml><return_code>FAIL</return_code><return_msg>"+returnInfo.getReturn_msg()+"</return_msg></xml>");
            }
            logger.warn("weixinCallBack-->{}",returnInfo.toString());
        }
        response.reset();
        response.getWriter().append(sb.toString());
    }
}
